#!/usr/bin/python
'''
/*
 * This computer program is the confidential information and proprietary trade
 * secret of VistaraIT LLC.  Possessions and use of this program must  conform
 * strictly to the license agreement between the user and VistaraIT LLC.,  and
 * receipt or possession does not convey any rights to divulge, reproduce,  or
 * allow others to use this program without specific written authorization  of
 * VistaraIT LLC.
 * 
 * Copyright (c) 2014 VistaraIT, Inc. All rights reserved.
 */
'''

from appliancemanager import ApplianceManager
from xml.dom import minidom
import os, time

from commons import executeCommand, parseUpdateResponse
import applicationproperties as properties
import logger

class LicenseManager(ApplianceManager):
 
    destFile = ''
    workdir = ''
    java_exec = ''
    license_jar = ''
    
    licensedir = ''
    licensefile = ''
    featurepack = ''
    
    workdir = ''
    newlicensefile = ''
    newfeaturepack = ''
    featurexml = ''
    nonfeaturexml=''
       
    features = []
    nonFeatures = []
    
    def __init__(self):
        super(LicenseManager,self).__init__()
        self.destFile = self.cfgmanager.getProperty(self.cfgmanager.DOWNLOAD_LICENSE)
        #current installed license files
        self.licensedir = self.cfgmanager.getProperty(self.cfgmanager.LICENSE_DIR)
        self.licensefile = self.licensedir + "/" + self.cfgmanager.getProperty(self.cfgmanager.LICENSE_FILE)
        self.featurepack = self.licensedir + "/" + self.cfgmanager.getProperty(self.cfgmanager.FEATUREPACKFILE)

        #new license files downloaded from remote lice 
        self.workdir = self.cfgmanager.getProperty(self.cfgmanager.LICENSE_WORK)
        self.newlicensefile = self.workdir + "/" + self.cfgmanager.getProperty(self.cfgmanager.LICENSE_FILE)
        self.newfeaturepack = self.workdir + "/" + self.cfgmanager.getProperty(self.cfgmanager.FEATUREPACKFILE)
        self.featurexml = self.workdir + "/" + self.cfgmanager.getProperty(self.cfgmanager.FEATUREXMLFILE)
        self.nonfeaturexml = self.workdir + "/" + self.cfgmanager.getProperty(self.cfgmanager.NONFEATUREXMLFILE)

        self.java_exec = self.cfgmanager.getProperty(self.cfgmanager.JAVA_EXEC)
        self.license_jar = self.cfgmanager.getProperty(self.cfgmanager.LICENSE_JAR)
        self.features = []
        self.nonFeatures = []
    
    def installLicense(self):
        try:
            result = self.getLicenseStatus()
            status = result['status']
            if status.lower() == "expired":
                if self.disableLicense() == True:
                    logger.logMessage(logger.INFO, 'license expired', 'Successfully disabled feature packs due to expired license.')
                else:
                    logger.logMessage(logger.ERROR, 'license expired', 'Failed to disable feature packs.')
                return False, "License file is expired."
            
            if status.lower() == "flush":
                if result['error-message'].lower() == "success":
                    return True, "Received flush. Successfully de-registered the appliance"
                else:
                    return False, "Received flush. Failed to de-registered the appliance. " + result['error-message']
                
            if status.lower() == "success":
                #Download the license file
                licenseId = result['licenseId']
                oldLicenseId = self.cfgmanager.getLicenseReachabilityProperty(self.cfgmanager.LICENSE_ID_INSTALLED)
                if oldLicenseId != 0 and oldLicenseId == licenseId:
                    return True, "New license ID is same as old license ID"

                if self.downloadLicenseFile(licenseId):
                    if self.getLicenseFiles() == False:
                        logger.logMessage(logger.ERROR, 'license', "Failed to get the license files.")
                        return False, "Failed to untar the license files."
                    licensetype="new_license"
                    #check old license is there or not
                    if os.path.exists(self.licensefile) and os.path.exists(self.featurepack):
                        licensetype = self.checkForNewLicense()
                    else:
                        #this is new license need to install for the first time
                        licensetype="new_license"
                        
                    if licensetype == "Failed":
                        logger.logMessage(logger.ERROR, 'license', "Failed to identify the license type.")
                        return False, "Failed to identify the license type."
                   
                    if licensetype == "old_license":
                        logger.logMessage(logger.INFO, 'license', "New license file is same as old license.")
                        return True, "New license file is same as old license"
                    
                    #separating feature and non features in the two individual files ( i.e feature XML , non feature XML)
                    if self.buildXML(self.newlicensefile, self.newfeaturepack) == False:
                        logger.logMessage(logger.ERROR, 'license', "Failed to generate feature pack XML files.")
                        return False, "Failed to generate feature pack XML files."
                    
                    #if it is the new-license copy new license files to the license directory
                    if licensetype == "new_license":
                        if self.updateLicense() == False:
                            logger.logMessage(logger.ERROR, 'license', "Failed to update license files")
                            return False, "Failed to update license files"
                    
                    #extract features and non features services
                    if self.getFeaturepackArrays() == False:
                        logger.logMessage(logger.ERROR, 'license', "Failed to get feature pack details.")
                        return False, "Failed to get feature pack details."
                    
                    #update services                
                    if self.updateServices() == False:
                        logger.logMessage(logger.ERROR, 'license', "Failed to update services.")
                        return False, "Failed to update services."
                else:
                    #save license reachability flag in configuration properties file
                    self.cfgmanager.saveLicenseReachability()
                    failedcount = int(self.cfgmanager.getLicenseReachabilityProperty(self.cfgmanager.LICENSE_COUNT))
                    stopcount = int(self.cfgmanager.getLicenseReachabilityProperty(self.cfgmanager.LICENSE_STOP_COUNT))
                    if stopcount <= failedcount:
                        if self.disableLicense() == True:
                            logger.logMessage(logger.INFO, 'license', 'Successfully disabled feature packs.')
                        else:
                            logger.logMessage(logger.ERROR, 'license', 'Failed to disable feature packs.')
                    logger.logMessage(logger.ERROR, 'license', 'Failed to download license files.')
                    return False, "Failed to download license files."
            else:
                logger.logMessage(logger.WARN, 'license', 'Not able to get License file: ' + result['error-message'])
                return False, "License Files are unavailable."
            
            if self.nonFeatures:
                expiredServices = "";
                for ser in self.nonFeatures:
                    expiredServices = expiredServices + ser + ","
                expiredString = expiredServices.trim(",") + " are either disabled or expired."
                logger.logMessage(logger.INFO, 'license', expiredString)
                return False, expiredString

            #reset the license reachability flag
            self.cfgmanager.saveLicenseReachability(True, licenseId)
            return True, "Successfully installed the license files."
        except:
            logger.logMessage(logger.ERROR, 'license', 'Received exception during installation of license files.')
            return False, "Received exception during installation of license files."
    
    '''
    This is for cron job
    '''
    def checkLicense(self):
        if os.path.exists(self.licensefile) and os.path.exists(self.featurepack):
            if not os.path.exists(self.workdir):
                os.mkdir(self.workdir)
                cmd = "/usr/bin/sudo chown admin.admin " + self.workdir + " >/dev/null 2>&1"
                executeCommand(cmd,[],True)
            else:
                cmd = "/bin/rm -f " + self.workdir + "/*"
                executeCommand(cmd)
            if self.buildXML(self.licensefile,self.featurepack) == False:
                logger.logMessage(logger.ERROR, 'license', "Failed to generate feature pack XML files.")
                return False
        else:
            logger.logMessage(logger.ERROR, 'license', "No License files were found.")
            
        if self.getFeaturepackArrays() == False:
            logger.logMessage(logger.ERROR, 'license', "Failed to get feature pack details.")
            return False
        
        if self.updateServices() == False:
            logger.logMessage(logger.ERROR, 'license', "Failed to update services.")
            return False
        return True
    
    def downloadLicenseFile(self,licenseId):
        url = self.toUpdateServerURL(properties.URL_LICENSE_DOWNLOAD+"&licenseId="+licenseId)
        return self.downloadFile(url,self.destFile)

    def getLicenseFiles(self):
        if not os.path.exists(self.workdir):
            os.mkdir(self.workdir)
            cmd = "/usr/bin/sudo chown admin.admin " + self.workdir + " >/dev/null 2>&1"
            executeCommand(cmd,[],True)
        else:
            cmd = "/bin/rm -f " + self.workdir + "/*"
            executeCommand(cmd)
        cmd = "unzip " + self.destFile + " -d " + self.workdir
        result = executeCommand(cmd)
        if result[0] != 0:
            logger.logMessage(logger.INFO, 'license', 'Failed to extract license files')
            cmd = "/bin/rm -f " + self.workdir + "/*"
            executeCommand(cmd)
            return False
        cmd = "/usr/bin/sudo chown admin.admin " + self.workdir + "/* >/dev/null 2>&1"
        executeCommand(cmd,[],True)
        logger.logMessage(logger.INFO, 'license', 'License files extracted Successfully')
        return True
    
    '''
    check the current license with newly downloaded license
    '''
    def checkForNewLicense(self):
        if os.path.exists(self.newlicensefile) and os.path.exists(self.newfeaturepack) and os.path.exists(self.licensefile) and os.path.exists(self.featurepack):
            cmd = self.java_exec + " -jar " + self.license_jar + " -compare -license " + self.licensefile + " -featurepack " + self.featurepack + " -newlicense " + self.newlicensefile + " -newfeaturepack " + self.newfeaturepack
            result = executeCommand(cmd,[],True)
            if result[0] == 51:
                logger.logMessage(logger.INFO, 'license', "New license file is different from old license.")
                return "new_license"
            elif result[0] == 52:
                logger.logMessage(logger.INFO, 'license', "New license file is same as old license.")
                return "old_license"
            else:
                logger.logMessage(logger.ERROR, 'license', "Failed to check the difference between new and old licenses.")
                return 'Failed'
        logger.logMessage(logger.ERROR, 'license', "File does not exists for checkNewLicense.")
        return 'Failed'    
    
    '''
    Build the feature xml,nonfeature xml files from the license files
    '''
    def buildXML(self,licensefile,featurepack):
        if os.path.exists(licensefile) and os.path.exists(featurepack):
            cmd = self.java_exec + " -jar " + self.license_jar + " -license " + licensefile + " -featurepack " + featurepack + " -featureXML " + self.featurexml + " -nonFeatureXML " + self.nonfeaturexml
            result = executeCommand(cmd,[],True)
            if result[0] == 75:
                logger.logMessage(logger.INFO, 'license', "Successfully created featurexml and non featurexml.")
                cmd = "/usr/bin/sudo chown admin.admin " + self.workdir + "/* >/dev/null 2>&1"
                executeCommand(cmd,[],True)
                return True
        logger.logMessage(logger.ERROR, 'license', "Failed to get featurexml and non featurexml.")
        return False
    
    '''
    Method to update license file
    ''' 
    def updateLicense(self):
        cmd = "cp -f " + self.newlicensefile + " " + self.licensefile
        result = executeCommand(cmd)
        if result[0] != 0:
            logger.logMessage(logger.ERROR, 'license', "Failed to update license.")
            return False
        
        cmd = "cp -f " + self.newfeaturepack + " " + self.featurepack
        result = executeCommand(cmd)
        if result[0] != 0:
            logger.logMessage(logger.ERROR, 'license', "Failed to update featurepack.")
            return False
        cmd = "/usr/bin/sudo chown admin.admin " + self.licensefile + " " + self.featurepack + " >/dev/null 2>&1"
        executeCommand(cmd,[],True)
        
        return True
    
    '''
    Getting feature pack details
    '''
    def getFeaturepackArrays(self):
        if os.path.exists(self.featurexml):
            xml = minidom.parse(self.featurexml)
            xmlFeatures = xml.getElementsByTagName("feature")
            for feature in xmlFeatures:
                service = feature.childNodes
                serviceName = service.item(0).nodeValue
                expireTag = feature.getElementsByTagName("expire")[0]
                nodes = expireTag.childNodes
                expireStatus = nodes.item(0).nodeValue
                if expireStatus != '' and serviceName != 'dra':
                    if expireStatus == 'false':
                        self.features.append(serviceName)
                    else:
                        logger.logMessage(logger.INFO, 'license', "Feature is expired -> " + serviceName)
                        self.nonFeatures.append(serviceName)
        else:
            logger.logMessage(logger.ERROR, 'license', "Feature pack file does not exists to create array.")
            return False
    
        if os.path.exists(self.nonfeaturexml):
            xml = minidom.parse(self.nonfeaturexml)
            xmlFeatures = xml.getElementsByTagName("feature")
            for feature in xmlFeatures:
                service = feature.childNodes
                serviceName = service.item(0).nodeValue
                if serviceName != '' and serviceName != 'dra':
                    self.nonFeatures.append(serviceName)
        else:
            logger.logMessage(logger.ERROR, 'license', "Non Feature pack file does not exists to create array.")
            return False
        return True
    
    '''
    Get the license information from Global Server
    '''  
    def getLicenseStatus(self):
        result = {}
        result['error-message'] = ''
        licenseData = self.prepareLicenseData("getLicenseID","cpe")
        logger.logMessage(logger.INFO, 'licenseRequest', licenseData)
        url = self.toUpdateServerURL(properties.URL_VPMG_LICENSE)
        
        try:
            status, response = self.postXMLData(url,licenseData)
        except Exception as (errno, errmsg):
            if errno == 111:
                logger.logMessage(logger.ERROR, 'Connection Exception', str(errno) + " - " + str(errmsg))
            elif errno == 101:
                logger.logMessage(logger.ERROR, 'Network Exception', str(errno) + " - " + str(errmsg))
            else:
                logger.logMessage(logger.ERROR, 'Caught Exception', str(errno) + " - " + str(errmsg))
            result['error-message'] = response
            result['status'] = 'Failed'
            return result

        logger.logMessage(logger.INFO, 'licenseResponse', str(status) + " " + str(response))
        if status != 200:
            result['error-message'] = response
            result['status'] = 'Failed'
            return result
        
        parseVal = parseUpdateResponse(response,"status")
        result['status'] = parseVal
        
        if parseVal == "invalid":
            latestConfArray = {}
            latestConfArray[self.cfgmanager.REGISTRATION_STATUS] = 'notreg'
            self.updateAppConf(latestConfArray)
            result['error-message'] = parseUpdateResponse(response,"errorMessage")
        elif parseVal == "no":
            result['error-message'] = properties.AUTO_SCH_NOUPDATES
        elif parseVal == "available":
            result['licenseId'] = parseUpdateResponse(response,"id")
            result['status'] = 'Success'
        elif parseVal == "flush":
            status, msg = self.appManager.resetApplianceToFactoryDefaults()
            logger.logMessage(logger.INFO, 'license flush', msg)
            if status:
                result['error-message'] = "Success"
            else:
                result['error-message'] = msg
        elif parseVal == "expired":
            result['error-message'] = parseUpdateResponse(response,"errorMessage")
        
        try:
            magicword = parseUpdateResponse(response, "magicword")
            if magicword != "":
                logger.logMessage(logger.INFO, 'license magic word', magicword)
                if magicword == "reboot":
                    cmd = "/usr/bin/sudo /sbin/reboot"
                    executeCommand(cmd, [], True)
                elif magicword == "reset":
                    status, msg = self.appManager.resetApplianceToFactoryDefaults()
                    logger.logMessage(logger.INFO, 'license magic word', str(status) + " - " + msg)
        except:
            pass

        return result
    
    '''
    Method to stop license
    '''
    def disableLicense(self):
        if self.checkLicense() == False:
            logger.logMessage(logger.ERROR, 'license', "Failed to check default license.")
            return False
        return True
    
    '''
    Method to delete license
    '''
    def deleteLicense(self):
        try:
            cmd = "/usr/bin/sudo /bin/rm -f " + self.licensefile
            executeCommand(cmd, [], True)
            cmd = "/usr/bin/sudo /bin/rm -f " + self.featurepack
            executeCommand(cmd, [], True)
            
            cmd = "/usr/bin/sudo /bin/rm -f " + self.destFile
            executeCommand(cmd, [], True)
            cmd = "/usr/bin/sudo /bin/rm -rf " + self.workdir
            executeCommand(cmd, [], True)

            ''' Delete the monit files '''
            cmd = "/usr/bin/sudo /bin/rm -rf " + properties.MONITRC_CFG_DIR + 'monitoring.monitrc'
            executeCommand(cmd, [], True)
            cmd = "/usr/bin/sudo /bin/rm -rf " + properties.MONITRC_CFG_DIR + 'neprobe.monitrc'
            executeCommand(cmd, [], True)

            cmd = "/usr/bin/sudo /home/admin/bin/servicemonit nagios stop"
            executeCommand(cmd, [], True)
            cmd = "/usr/bin/sudo /home/admin/bin/servicemonit neprobe stop"
            executeCommand(cmd, [], True)

            self.cfgmanager.saveLicenseReachability(True)
            if self.updateMonit():
                logger.logMessage(logger.INFO, 'delete license', "Successfully deleted license files and updated monit")
                return True
            else:
                logger.logMessage(logger.ERROR, 'delete license', "Failed to update monit")
                return False
        except:
            logger.logMessage(logger.ERROR, 'delete license', "Failed to delete license. Exception Caught")
            return False

    '''
    Method to update services
    '''
    def updateServices(self):
        try:
            status = True
            for serviceA in self.nonFeatures,self.features:
                for service_id in serviceA:
                    service = self.service_map[service_id]
                    cmd = properties.CMD_SUDO + " /home/admin/bin/servicemonit " + service + " stop"
                    result = executeCommand(cmd,[],True)
                    logger.logMessage(logger.INFO, 'license', service + ": " + result[1])
                    if result[0] != 1:
                        cmd = properties.CMD_SUDO + " /home/admin/bin/servicemonit " + service + " status"
                        result = executeCommand(cmd,[],True)
                        logger.logMessage(logger.ERROR, 'license', "Failed to stop the service : " + result[1])
                
            if self.updateMonit(self.features) == False:
                logger.logMessage(logger.ERROR, 'license', "Failed to reload MONIT service.")
                status = False
            time.sleep(10)
            
            for service_id in self.features:
                service = self.service_map[service_id]
                cmd = properties.CMD_SUDO + " /home/admin/bin/servicemonit " + service + " start"
                result = executeCommand(cmd, [], True)
                logger.logMessage(logger.INFO, 'license', service + ": " + result[1])
                if result[0] != 0:
                    cmd = properties.CMD_SUDO + " /home/admin/bin/servicemonit " + service + " status"
                    result = executeCommand(cmd,[],True)
                    logger.logMessage(logger.ERROR, 'license', "Failed to start the service : " + result[1])
                    status = False
        except Exception as Err:
            logger.logMessage(logger.ERROR, 'license', "Exception caught: " + str(Err))
            status = False
        return status
